package com.lenovo.leos.filebrowser.netdisk;

import java.util.HashMap;
import java.util.LinkedList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.lenovo.leos.letools.lenovodata.BaseNetClientServer;
import com.lenovo.leos.letools.utils.ListFileUseParams;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.content.Context;


import com.lenovo.leos.filebrowser.R;
import com.lenovo.leos.filebrowser.netdisk.NetDiskConstant;


// [improve] maybe use a super class to abstract some detail
public class SimpleNetDiskOpThread extends Thread {
	private static final String TAG = "SimpleNetDiskOpThread";
	private static final String TAG_NETTOOL_SDK_RET = "BY_YANGZHIHAO";
	private boolean mbStop = false;
	private boolean mbNeedNotify = false;
	
	private LinkedList<SimpleNetDiskOp> mllOps = null;
	private HashMap<Long, NetDiskOp> mhmDone = null;
	private Context mContext = null;
	BaseNetClientServer	mSerOP;
	public SimpleNetDiskOpThread(Context context, LinkedList<SimpleNetDiskOp> opList, 
			HashMap<Long, NetDiskOp> hmDone){
		if (null == context || null == opList || null == hmDone){
			Log.e(TAG, "invalid parameter in SimpleNetDiskOpThread");
			return;
		}else{
			mllOps = opList;
			mhmDone = hmDone;
			mContext = context; 
		}
		mSerOP = new BaseNetClientServer();
	}
	
	public void toStop(){
		if (!mbStop)
			mbStop = true;
	}
	
	public void setEnableNotify(boolean enable){
		mbNeedNotify = enable;
	}
	  
	
	private void doLogin(SimpleNetDiskOp op){
		Log.i(TAG, "==> doLogin");
		String retJson = null;
		try {
			Log.i(TAG,"chaojidaniub1111");  
			retJson = mSerOP.login(mContext, op.getData().getString("user_name"), op.getData().getString("password"));
			
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			 
		} catch (Exception e) {
			Log.i(TAG,"chaojidaniub");
			retJson= "{\"result\":2}";
			Log.i(TAG,retJson);
			e.printStackTrace();   
			//add by gaoge 2011-04-27,when the The operation timed out,close the wait dialog,
			//and show the error dialog
			ProgressMessageDialog.cancelDialog();
			ErrorMessageDialog.showMessageDialog(mContext, mContext.getString(R.string.net_error));
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		if (null != retJson)
			op.setResult(retJson);
	}
	
	private void doGetSpace(SimpleNetDiskOp op){

		Log.i(TAG, "==> doGetSpace");
		String retJson  = null;
		try {
			retJson = mSerOP.getSpace(mContext);
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			op.setResult(retJson);
			
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
			
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		
	}
	
	// [improve] check empty issue
	private void doGetDirContent(SimpleNetDiskOp op) {
		Log.i(TAG, "==> doGetDirContent");
		
//		op.getData().getString("dirpath")
		
		JSONArray jsoDir = null;
		
		String dirid = op.getData().getString("dirid");
		String parent = op.getData().getString("dirpath");

		try {
			String subDirs = mSerOP.listDir(mContext, dirid);
			Log.i(TAG, "the json subdirs string is " + subDirs);
			
			if (null != subDirs){
				JSONObject jso = new JSONObject(subDirs);
				Log.i(TAG, "jso is : " + jso.toString());
				int res = jso.getInt("result");
				Log.i(TAG, "result is " + res);
				
				switch (res){
				case 0: 
					op.setState(SimpleNetDiskOp.State.error);
					op.setResult("failed");	
					return;
				case 1:
					Log.i(TAG, "result is 1");
					jsoDir = jso.getJSONArray("list");
					if (null == jsoDir){
						// error
					}
					break;
				default:
					break;
				}
			}		
			
			Log.i(TAG_NETTOOL_SDK_RET, "the dirs is " + jsoDir.toString());
	
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		JSONArray jsoFile = null;
		
		try {
			
			ListFileUseParams params = new ListFileUseParams();
			params.dirid = dirid;
			
			String subFiles = mSerOP.listFile(mContext, params);
			Log.i(TAG, "the json subdirs string is " + subFiles);
			
			if (null != subFiles){
				JSONObject jso = new JSONObject(subFiles);
				int res = jso.getInt("result");
				
				switch (res){
				case 0: 
					op.setState(SimpleNetDiskOp.State.error);
					op.setResult("failed");	
					return;
				case 1:
					jsoFile = jso.getJSONArray("list");
					if (null == jsoDir){
						// error
					}
					break;
				default:
					break;
				}
			}
			
			Log.i(TAG_NETTOOL_SDK_RET, "files is " + jsoFile.toString());
			
		} catch (Exception e) {
			
			e.printStackTrace();
		}
		
		JSONObject njso = null;
		if (null != jsoFile && null != jsoDir){
			njso = new JSONObject();
			try {
				njso.put("result", 1);
				njso.put("parent", parent);
				njso.put("dirlist", jsoDir);
				njso.put("filelist", jsoFile);
				
				Log.i(TAG, "the new jso is " + njso.toString());
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			op.setState(SimpleNetDiskOp.State.finish);
			op.setResult(njso.toString());			
		}else{
			op.setState(SimpleNetDiskOp.State.error);
			op.setResult("failed");			
		}

	}
	
	private void doListSubDirInDir(SimpleNetDiskOp op) {
		Log.i(TAG, "==> doListSubDirInDir");
		
		try {
			String retJson = mSerOP.listDir(mContext, op.getData().getString("dirpath"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		op.setResult("ok");
	}
	
	private void doListFilesInDir(SimpleNetDiskOp op) {
		Log.i(TAG, "==> doListFilesInDir");
		
		try {
			ListFileUseParams params = new ListFileUseParams();
			params.dirid = op.getData().getString("dirpath");
			
			String retJson = mSerOP.listFile(mContext, params);
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		op.setResult("ok");
	}
	
	private void doCreateDir(SimpleNetDiskOp op) {
		Log.i(TAG, "==> doListSubDirInDir");
		String retJson = null;
		try {
			
			retJson= mSerOP.createDir(mContext, op.getData().getString("parentid"),op.getData().getString("name"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			if(null == retJson || retJson.trim().length() == 0){
				
			}else{
				JSONObject nJson = new JSONObject(retJson);
				nJson.put("name",op.getData().getString("name"));
				nJson.put("parent",op.getData().getString("parent"));
				op.setResult(nJson.toString());
			}
			
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
		}
		op.setState(SimpleNetDiskOp.State.finish);
	}
	
	private void doDeleteDir(SimpleNetDiskOp op) {
		String retJson = null;
		try {
			
			retJson = mSerOP.delDir(mContext, op.getData().getString("dirpath"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			op.setResult(retJson);
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		
	}
	
	private void doRenameDir(SimpleNetDiskOp op) {
		String retJson = null;
		try {
			
			 retJson = mSerOP.renameDir(mContext, op.getData().getString("dirpath"), op.getData().getString("newname"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			if(retJson ==null || retJson.trim().length() ==0){
			}else{
				JSONObject json = new JSONObject(retJson);
				if(json == null){
					
				}else{
					json.put("dirid", op.getData().getString("dirpath"));
					json.put("dirname", op.getData().getString("newname"));
					json.put("parent", op.getData().getString("parent"));
					json.put("type", op.getData().getString("type"));
					op.setResult(json.toString());
					Log.i(TAG_NETTOOL_SDK_RET,json.toString());
				}
			}
			
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		
	}
	
	private void doMoveDir(SimpleNetDiskOp op) {
		String retJson =null;
		try {
			retJson = mSerOP.moveDir(mContext,op.getData().getString("filepath"),op.getData().getString("newpath"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			op.setResult("ok");
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		
	}
	
	private void doDeleteFile(SimpleNetDiskOp op) {
		String retJson = null;
		try {
		
			retJson =mSerOP.deleteFile(mContext,op.getData().getString("filepath"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			op.setResult(retJson);
			
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		
	}
	
	private void doRenameFile(SimpleNetDiskOp op) {
		String retJson  = null;
		try {
		
			retJson = mSerOP.renameFile(mContext,op.getData().getString("filepath"),op.getData().getString("newname"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			if(retJson ==null || retJson.trim().length() ==0){
			}else{
				JSONObject json = new JSONObject(retJson);
				if(json == null){
					
				}else{
					json.put("fileid", op.getData().getString("filepath"));
					json.put("filename", op.getData().getString("newname"));
					json.put("parent", op.getData().getString("parent"));
					json.put("type", op.getData().getString("type"));
					op.setResult(json.toString());
					Log.i(TAG_NETTOOL_SDK_RET,json.toString());
				}
			}
			
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		
	}
	
	private void doMoveFile(SimpleNetDiskOp op) {
		String retJson  = null;
		try {
			
			retJson = mSerOP.moveFile(mContext, op.getData().getString("filepath"), op.getData().getString("newpath") ,op.getData().getString("override"));
			Log.i(TAG_NETTOOL_SDK_RET,retJson);
			
		} catch (Exception e) {
			retJson= "{\"result\":2}";
			op.setResult(retJson);
			e.printStackTrace();
		}
		
		op.setState(SimpleNetDiskOp.State.finish);
		
	}
	
	private void notifyIfNeed (SimpleNetDiskOp op) {
		if (mbNeedNotify){
				
			Bundle data = op.getData();
			if (null != data){
				data.putLong(NetDiskConstant.OP_DATA_KEY_ID, op.getID());
				data.putString(NetDiskConstant.OP_DATA_KEY_RES, op.getResult());
			}
			
			if (null != data){
				Intent intent = new Intent();
				intent.setAction(NetDiskConstant.ACTION_NOTIFY_RESULT);
				intent.putExtras(data);
				
				Log.i(TAG, "notify the op result");
				mContext.sendBroadcast(intent);
			}
		}
	}
	
	public void run() {
		
		while (!mbStop) {
//			Log.i(TAG, "==> run of SimpleNetDiskOpThread");
			if (null == mllOps || 0 == mllOps.size()){
				try {
					Thread.sleep(100);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}else{
				SimpleNetDiskOp nextOp = null;
				
				// get the next op 
				while (true){
					if (0 == mllOps.size()){
						Log.i(TAG, "no op in stack");
						break;
					}else{
		//change sdk version 2.3.3 to 2.0 modify by yangzhihao		
		//				SimpleNetDiskOp sop = mllOps.peekFirst();
		//				mllOps.peek();
						SimpleNetDiskOp sop = null;
						if(!mllOps.isEmpty())
						{
							sop = mllOps.getFirst();
						}
						else
						{
							sop = null;
						}
						if (null == sop){
							Log.e(TAG, "no op in stack but size is not zero");
							break;
						}else{
							if (SimpleNetDiskOp.State.ready == sop.getState()){
								nextOp = sop;
								break;
							}else if (SimpleNetDiskOp.State.finish == sop.getState()){
								continue;
							}else{
								Log.e(TAG, "the op state is invalid");
								continue;
							}
						}
					}
				}
				
				if (null == nextOp)
					continue;
				
				SimpleNetDiskOp sop = (SimpleNetDiskOp) nextOp.clone();
				SimpleNetDiskOp.Type type = sop.getType();
				
				if (SimpleNetDiskOp.Type.login == type){
					doLogin(sop);
				}else if (SimpleNetDiskOp.Type.get_space == type){
					doGetSpace(sop);
				}else if (SimpleNetDiskOp.Type.list_subdir_in_dir == type) {
					doListSubDirInDir(sop);
				}else if (SimpleNetDiskOp.Type.list_files_in_dir == type){
					doListFilesInDir(sop);
				}else if (SimpleNetDiskOp.Type.create_dir == type) {
					doCreateDir(sop);
				}else if (SimpleNetDiskOp.Type.delete_dir == type) {
					doDeleteDir(sop);
				}else if (SimpleNetDiskOp.Type.rename_dir == type) {
					doRenameDir(sop);
				}else if (SimpleNetDiskOp.Type.move_dir == type) {
					doMoveDir(sop);
				}else if (SimpleNetDiskOp.Type.delete_file == type) {
					doDeleteFile(sop);
				}else if (SimpleNetDiskOp.Type.rename_file == type) {
					doRenameFile(sop);
				}else if (SimpleNetDiskOp.Type.move_file == type) {
					doMoveFile(sop);
				}else if (SimpleNetDiskOp.Type.get_dir_content == type){
					doGetDirContent(sop);
				}else{
					Log.e(TAG, "unknown simple op type");
				}
				
				// move the state to mhmDone if necessory
				SimpleNetDiskOp.State state  = sop.getState();
				if (SimpleNetDiskOp.State.error == state 
						|| SimpleNetDiskOp.State.finish == state){
					Log.i(TAG, "move sop to mhmDone");
					mllOps.remove(nextOp);
					mhmDone.put(sop.getID(), sop);
					
					notifyIfNeed(sop);
				}
			}
			
			// [improve] maybe sleep a while
			// keep more time for other threads
//			try {
//				Thread.sleep(100);
//			} catch (InterruptedException e1) {
//				e1.printStackTrace();
//			}
			
		}//while
	}
}